home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Games Room
/
The Games Room.iso
/
amiga
/
board_games
/
backgammon
/
backscreen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-24
|
17KB
|
610 lines
/************************************************************************/
/* Hoser BackGammon version 1.0 */
/* Robert Pfister */
/* Rfd#3 Box 2340 home:(207)-873-3520 */
/* Waterville, Maine 04901 */
/* */
/* Pfister_rob%dneast@dec.decwrl */
/* */
/* Copyright June,1987 all rights reserved. */
/* */
/* This program will play a game of backgammon at the novice level */
/* */
/* The code is in 4 parts... */
/* 1) back.c - main driver */
/* / 2) eval.c - evaluation of moves */
/* \/ 3) backscn.c - screen stuff.. */
/* 4) backmenu.c - menu stuff, help text, and ``decoder'' */
/* */
/* this was compiled under Manx 3.20a, using long integers */
/* */
/* This file contains: */
/* gen_points PutIntuiText ITextLen Gsetup */
/* ShowDice PutMoveNumber PutPiece decode */
/* DoMenuStrip UndoMenuStrip requestor finit */
/* PutBarPiece PutSpike BlinkPiece TextScreen */
/************************************************************************/
/* Most recent modification: 3/ 8/93 */
/* Most recent modification: 11/28/94 */
/* Most recent modification: 2/24/95 */
#include <proto/intuition.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/diskfont.h>
#include <clib/alib_protos.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "back.h"
#define max_vector 16 /* for AreaMove/Draw */
#define piece_width 32
#define sign(x) (x < 0 ? -1 : +1)
typedef
struct {
SHORT x,y;} coord;
typedef
/* order of points in box[] is upper left, lower right or */
/* left, top, right, bottom as individual values */
/* Spike entry is coordinates of spike point */
struct {
coord box[2];
coord spike;} point_rec;
typedef
struct {
short count,
height;
coord point[13];} shape_rec;
static const shape_rec
laced_piece =
{12, 23,
{{ 13, 2}, { 11, 6}, { 4,10}, { -4,10},
{-11, 6}, {-13, 2}, {-13,-2}, {-11,-6},
{ -4,-10}, { 4,-10}, { 11,-6}, { 13,-2}}},
norm_piece =
{12, 11,
{{ 13, 1}, { 11, 3}, { 3, 5}, { -3, 5},
{-11, 3}, {-13, 1}, {-13,-1}, {-11,-3},
{ -3,-5}, { 3,-5}, { 11,-3}, { 13,-1}}};
static point_rec point[26];
int minY; /* has to be global */
static int xc, yc, /* center of board */
minX, maxX, /* horizontal limits */
/*minY,*/ maxY, /* vertical limits */
h_pitch, /* width of spike */
height, /* spike height */
move_num_left, /* where move number starts */
move_num_len, /* how long it plots */
bar_left, bar_right; /* limits of bar */
static shape_rec *piece_ptr = &norm_piece;
UWORD color_table[] =
{0x407,0xDDD,0x0F0,0xFF0,0xF00,0x000,0x00F,0xEEE};
struct ColorMap color_map =
{0,0,sizeof(color_table) / 2,(APTR)&color_table};
char MyTitle[] =
"Hoser BackGammon Copyright June 1987 Robert Pfister";
struct RastPort *rp;
struct Screen *screen = NULL;
static struct ViewPort *vp;
extern struct Menu MyMenu[]; /* get the menu somewhere else */
struct Window *w = NULL;
struct TextAttr font[] = {{"topaz",8,0,0},{"courier.font",13,0,0}};
struct TextFont *tf = NULL;
struct NewScreen ns = {
0,0,-1,-1,3, 0,1, HIRES, CUSTOMSCREEN,font, MyTitle, NULL,NULL};
struct NewWindow nw = {
0,10,-1,190,0,1, CLOSEWINDOW | MOUSEBUTTONS | MENUPICK,
SMART_REFRESH | ACTIVATE | WINDOWDRAG | WINDOWDEPTH, NULL,NULL,
"Backgammon anyone?", NULL,NULL, 0,0,640,200,CUSTOMSCREEN };
struct NewWindow crnw = {
20,0,405,0,0,1, /* top and height set when used */
MOUSEBUTTONS, SMART_REFRESH | ACTIVATE | WINDOWDRAG,
NULL,NULL, "Backgammon credits", NULL,NULL, 0,0,640,200,CUSTOMSCREEN };
static short AreaBuf[max_vector * 5 / sizeof(short)];
static APTR TBuf;
static struct TmpRas TRas;
static struct AreaInfo AInfo;
BOOL laced;
void gen_points(struct Window *wp)
{ /* adjust board for screen/window size */
int bar_width, /* the obvious */
d, n;
point_rec *prp;
minX = 3;
maxX = wp->Width - 3;
bar_width = 8;
h_pitch = (maxX - minX - bar_width) / 12;
bar_width = maxX - minX - 12 * h_pitch;
if (bar_width > 10) {
minX += (bar_width - 10) / 2;
maxX -= (bar_width - 10) / 2;
bar_width = maxX - minX - 12 * h_pitch;
}
xc = (minX + maxX) / 2;
bar_left = xc - bar_width / 2;
bar_right = bar_left + bar_width;
minY = screen->Font->ta_YSize * 3 + 1;
maxY = wp->Height - 4;
height = ((maxY - minY) * 3 / 7);
yc = (minY + maxY) / 2;
d = 0;
prp = point + 1;
for (n = 0; n < 12; n++) {
prp->box[1].x = (prp->box[0].x = minX + n * h_pitch + d) + h_pitch - 1;
prp->spike.y =
prp->box[0].y = (prp->box[1].y = maxY) - height;
prp->spike.x = prp->box[0].x + h_pitch / 2;
if (n == 5)
d = bar_width;
prp++;
}
for (n = 11; n >= 0; n--) {
prp->box[1].x = (prp->box[0].x = minX + n * h_pitch + d) + h_pitch - 1;
prp->box[0].y = minY;
prp->spike.y =
prp->box[1].y = (prp->box[0].y = minY) + height;
prp->spike.x = prp->box[0].x + h_pitch / 2;
if (n == 6)
d = 0;
prp++;
}
prp = point;
prp->box[0].x = xc - 10;
prp->box[0].y = maxY - height;
prp->box[1].x = xc + 10;
prp->box[1].y = yc + 5;
prp->spike.x = xc;
prp->spike.y = yc + 9;
prp = point + 25;
prp->box[0].x = xc - 10;
prp->box[0].y = maxY + height;
prp->box[1].x = xc + 10;
prp->box[1].y = yc - 5;
prp->spike.x = xc;
prp->spike.y = yc - 9;
}
void PutIntuiText(char *s, int x, int y, int color)
{
struct IntuiText it = {1, 0, JAM2, 0, 0, NULL, NULL, NULL};
it.FrontPen = color;
it.LeftEdge = x;
it.TopEdge = y;
it.IText = s;
PrintIText(w->RPort, &it, 0, 0);
}
int ITextLen(char *s)
{
struct IntuiText it = {1, 0, JAM2, 0, 0, NULL, NULL, NULL};
it.IText = s;
return IntuiTextLength(&it);
}
void Gsetup(void)
{
struct Preferences prefs;
GetPrefs(&prefs, sizeof prefs);
if (laced = (prefs.LaceWB & LACEWB)) {
ns.ViewModes |= LACE;
ns.Font = &font[1];
tf = OpenDiskFont(&font[1]);
piece_ptr = &laced_piece;
}
if (!(nw.Screen = screen = OpenScreen(&ns))) {
finit();
Alert(1);
exit(1);
}
nw.Width = screen->Width;
nw.TopEdge = screen->TopEdge + screen->Font->ta_YSize + 2;
nw.Height = screen->Height - nw.TopEdge;
if (!(w = OpenWindow(&nw))) {
finit();
Alert(2);
exit(2);
}
vp = &screen->ViewPort;
rp = w->RPort;
/* intialize temporary area space */
InitArea(&AInfo, AreaBuf, max_vector);
rp->AreaInfo = &AInfo;
if (!(TBuf = (APTR)AllocRaster(screen->Width, screen->Height))) {
finit();
Alert(3);
exit(3);
}
gen_points(w);
SetMenuStrip(w,MyMenu);
rp->TmpRas = &TRas;
InitTmpRas(&TRas, (char *)TBuf, RASSIZE(screen->Width, screen->Height));
LoadRGB4(vp, color_table, 8);
SetDrMd(rp, JAM1);
SetAPen(rp, back_color);
RectFill(rp, minX, minY, maxX - 1, maxY);
SetAPen(rp, tm1_color);
RectFill(rp, bar_left, minY, bar_right, maxY);
/* write evaluation count at top of window */
move_num_len = ITextLen("Number of Moves Evaluated: ");
move_num_left = minX + 2 + move_num_len;
PutIntuiText("Number of Moves Evaluated:", minX + 2,
minY - screen->Font->ta_YSize - 2, dice_color);
{
struct DateStamp time;
DateStamp(&time);
srand(time.ds_Tick);
}
}
void ShowDice(BYTE d[4], int c)
{ /* put dice on the screen */
int yu, yl;
char line[] = " ";
struct IntuiText it = {1, 0, JAM1, 0, 0, NULL, NULL, NULL};
/* cover up dice with dice color */
yu = yc - screen->Font->ta_YSize / 2;
yl = yu + screen->Font->ta_YSize;
SetAPen(rp, dice_color);
RectFill(rp, xc-27, yu , xc+27, yl);
if (d[0] && d[1]) {
/* put in the numbers for the left and right die */
it.FrontPen = piece2_color;
if (c == Uside)
it.FrontPen = piece1_color;
line[0] = '0' + d[0];
line[4] = '0' + d[1];
it.LeftEdge = xc - piece_width / 2;
it.TopEdge = yu + 1;
it.IText = line;
PrintIText(w->RPort, &it, 0, 0);
SetAPen(rp, tm1_color);
RectFill(rp, bar_left, yu, bar_right - 1, yl);
}
}
void PutMoveNumber(int Number)
{ /* only calls are from EVAL */
char Line[8];
sprintf(Line,"%5d ",Number);
PutIntuiText(Line, move_num_left,
minY - screen->Font->ta_YSize - 2, dice_color);
}
void PutPiece(long x, long y, long color)
{ /* coords are for center of piece */
int i;
shape_rec *sp = piece_ptr;
SetAPen(rp,color);
AreaMove(rp, x + sp->point[sp->count - 1].x, y + sp->point[sp->count - 1].y);
for (i = 0; i < sp->count; i++)
AreaDraw(rp, x + sp->point[i].x, y + sp->point[i].y);
AreaEnd(rp);
}
int decode(int x, int y) /* return the 'spike' number given the screen */
{ /* point relative to upper left corner of the window */
int point,
disp = 0,
font_height = screen->Font->ta_YSize;
if (x > xc)
disp = bar_right - bar_left;
/* check if dice 'clicked'...indicate unusual end of turn */
if ((y > (yc - font_height / 2)) && (y < (yc + font_height / 2)) &&
(x > xc - 27) && (x < xc + 27))
return(-1);
/* check if 'bar' selected */
if ((x > (xc - piece_width / 2)) && (x < (xc + piece_width / 2)) &&
( y > (font_height - 2 - piece_ptr->height)) &&
(y < (yc - font_height / 2 - 2)))
point = 0;
else
point = 1 + (x + disp - minX) / h_pitch;
if ( y < yc)
point = 25 - point;
return(point);
}
static int ErrSet=FALSE;
void DoMenuStrip(char errmsg[])
{
ErrSet=TRUE;
SetWindowTitles(w, (char *)-1, errmsg);
}
void UnDoMenuStrip(void)
{
if (ErrSet == TRUE) {
SetWindowTitles(w, (char *)-1, MyTitle);
ErrSet = FALSE;
}
}
/* put up a plain old requestor given three strings
name... the question/statement of the requestor
yes... the affirmative response
no... the negative response
this returns 'true' for the yes, 'false' for the no */
BOOL requestor(char name[], char yes[], char no[])
{
const static struct IntuiText
Rt = {tm1_color, tm2_color, JAM2, 50, 10, NL, (char *)0, NL},
Rr = {spike2_color, spike1_color, JAM1, 8, 3, NL, (char *)0, NL};
struct IntuiText Rbody, Rright, Rleft;
Rbody = Rt; Rright = Rr; Rleft = Rr;
Rleft.IText = no; Rright.IText = yes; Rbody.IText = name;
return(AutoRequest(w, &Rbody, &Rleft, &Rright, 0, 0, 300, 90));
}
extern you_me_rec you, me;
extern USHORT total_games;
void finit(void)
{
char *s[] = {
"Running totals",
"\n",
"\n",
" Total games xxxxxx\n",
" You Me\n",
" Dice total xxxxxxxxxx xxxxxxxxxx\n",
" Average roll xx.x xx.x\n",
" Incomplete xxxxxxxxxx xxxxxxxxxx\n",
" Wasted xxxxxxxxxx xxxxxxxxxx\n",
"\n",
" [click in window to terminate] \n"};
if (total_games) {
sprintf(&s[3][13], "%6d\n", total_games);
sprintf(&s[5][14], "%10d %10d\n", you.total.roll, me.total.roll);
sprintf(&s[6][20], "%4.1f %4.1f\n",
(float)you.total.average_roll / total_games,
(float)me.total.average_roll / total_games);
sprintf(&s[7][14], "%10d %10d\n", you.total.incomplete, me.total.incomplete);
sprintf(&s[8][14], "%10d %10d\n", you.total.wasted, me.total.wasted);
TextScreen(s, 11);
}
if (TBuf) FreeRaster(TBuf, screen->Width, screen->Height);
if (w) CloseWindow(w);
if (screen) CloseScreen(screen);
if (laced) CloseFont(tf);
}
void PutBarPiece(int y, int pieces, int inc, int color)
{
char line[4];
struct IntuiText it = {1, 0, JAM1, 0, 0, NULL, NULL, NULL};
SetAPen(rp, back_color);
RectFill(rp, xc - piece_width, y, xc + piece_width, y + inc);
SetAPen(rp, tm1_color);
RectFill(rp, bar_left, y, bar_right - 1, y + inc);
pieces = abs(pieces);
if (pieces != 0) {
PutPiece(xc, y + inc / 2, color);
if (pieces > 1) {
sprintf(line, "%d", pieces);
it.FrontPen = dice_color;
it.LeftEdge = bar_left;
it.TopEdge = y + 2;
it.IText = line;
PrintIText(w->RPort, &it, 0, 0);
}
}
}
void PutSpike(int spk, int pieces)
{
long color, inc, x, y;
char line[4];
/* pick color of the pieces */
if (pieces < 0)
color = piece1_color;
else
color = piece2_color;
inc = - piece_ptr->height;
if (spk > 12)
inc = -inc;
if (spk == 0) /* plot my ones on the bar */
PutBarPiece(yc + screen->Font->ta_YSize, pieces, -inc, color);
else if (spk == 25) /* plot yours on the bar */
PutBarPiece(yc - screen->Font->ta_YSize - inc, pieces, inc, color);
else { /* all the rest */
int i;
point_rec *pp;
pp = &point[spk];
/* box in the area around the spike with background color...*/
SetAPen(rp, back_color);
RectFill(rp, pp->box[0].x, pp->box[0].y, pp->box[1].x, pp->box[1].y);
if (spk & 1)
SetAPen(rp, spike1_color);
else
SetAPen(rp, spike2_color);
if (spk < 13) { /* lower spikes */
AreaMove(rp,pp->box[0].x,pp->box[1].y); /* lower left corner */
AreaDraw(rp,pp->box[1].x,pp->box[1].y); /* lower right corner */
AreaDraw(rp,pp->spike.x,pp->spike.y); /* point of spike */
AreaDraw(rp,pp->box[0].x,pp->box[1].y); /* lower left corner */
AreaEnd(rp);
}
else { /* upper spikes */
AreaMove(rp,pp->box[0].x,pp->box[0].y); /* upper left corner */
AreaDraw(rp,pp->box[1].x,pp->box[0].y); /* upper right corner */
AreaDraw(rp,pp->spike.x,pp->spike.y); /* point of spike */
AreaDraw(rp,pp->box[0].x,pp->box[0].y); /* upper left corner */
AreaEnd(rp);
}
if (pieces < 0)
pieces = -pieces;
/* go through number of pieces, up to "PerSpike" */
x = pp->spike.x;
y = pp->box[1].y;
if (spk > 12)
y = pp->box[0].y;
y += inc / 2;
inc += 2 * sign(inc);
for(i = 0; (i < pieces) && (i < PerSpike); i++) {
PutPiece(x, y, color);
y += inc;
}
/* put some fancy numbers on it if > PerSpike pieces */
if (pieces > PerSpike) {
sprintf(line,"%2d",pieces);
y = pp->box[1].y - 2;
if (spk > 12)
y = pp->box[0].y + 8;
Move(rp, x - screen->Font->ta_YSize, y);
SetAPen(rp, dice_color);
Text(rp, line, 2);
}
}
} /* end of PutSpike */
void BlinkPiece(BYTE board[], int pos)
{
int x, y, i, color, inc;
point_rec *pp;
if (board[pos]) { /* Don't bother if nothing there */
pp = &point[pos];
x = pp->spike.x;
inc = piece_ptr->height;
if ((pos == 0) || (pos == 25))
y = pp->spike.y;
else {
inc = -piece_ptr->height;
y = pp->box[1].y;
if (pos > 12) {
inc = -inc;
y = pp->box[0].y;
}
y += inc / 2;
y += 2 * sign(inc);
}
if ((pos != 0) && (pos != 25))
y += (min(abs(board[pos]), PerSpike) - 1) * inc;
color = piece2_color;
if (board[pos] < 0)
color = piece1_color;
for(i = 2; i >= 0; i--) {
Delay(1);
switch (pos) {
case 0:
PutBarPiece(yc + screen->Font->ta_YSize, board[0], inc, color);
break;
case 25:
PutBarPiece(yc - screen->Font->ta_YSize - inc, board[25], inc, color);
break;
default:
PutPiece(x, y, dice_color);
}
Delay(1);
switch (pos) {
case 0:
PutBarPiece(yc + screen->Font->ta_YSize, board[0], inc, color);
break;
case 25:
PutBarPiece(yc - screen->Font->ta_YSize - inc, board[25], inc, color);
break;
default:
PutPiece(x, y, color);
}
}
PutSpike(pos, board[pos]);
}
}
void TextScreen(char *stuff[], int num)
{
int i, n, longest = 0;
unsigned long Class;
struct IOStdReq *wr;
struct MsgPort *wrp;
struct Window *crw;
struct IntuiMessage *message;
const char cons_init[] = "\2330 p";
struct IntuiText it = {1, 0, JAM1, 0, 0, NULL, NULL, NULL};
for (i = 1; i <= num; i++) {
it.IText = stuff[i];
if ((n = IntuiTextLength(&it)) > longest)
longest = n;
}
crnw.Width = min(longest +10, screen->Width);
crnw.LeftEdge = (screen->Width - crnw.Width) / 2;
crnw.Height = (num + 1) * screen->Font->ta_YSize;
crnw.TopEdge = (maxY - crnw.Height) / 2;
crnw.Screen = screen;
crnw.Title = stuff[0];
crw = (struct Window *)OpenWindow(&crnw);
if (crw != NULL) {
wrp = CreatePort("my.con.write",0);
wr = CreateStdIO(wrp);
wr->io_Data = (APTR) crw;
wr->io_Length = sizeof(struct Window);
if (OpenDevice("console.device", 0, (struct IORequest *)wr, 0) == 0) {
wr->io_Command = CMD_WRITE;
wr->io_Length = -1;
wr->io_Data = (APTR)cons_init;
DoIO((struct IORequest *)wr);
/* loop through all the stuff and put it to the open'd console */
for (i = 1; i < num; i++) {
wr->io_Length = -1;
wr->io_Data = (APTR)stuff[i];
DoIO((struct IORequest *)wr);
}
/* close the console */
CloseDevice((struct IORequest *)wr);
DeleteStdIO(wr);
DeletePort(wrp);
}/* end-if console created */
for (;;) {
Wait(1L << crw->UserPort->mp_SigBit);
message = (struct IntuiMessage *) GetMsg(crw->UserPort);
Class = message->Class;
ReplyMsg((struct Message *)message);
if (Class == MOUSEBUTTONS)
break;
}
CloseWindow(crw);
} /* end-if window opened */
}